from fastapi import APIRouter, HTTPException, status, Depends
from pydantic import BaseModel
from datetime import datetime
from typing import Optional, Dict, Any
from functools import wraps
import copy
from tools.jwt_tool import jwt_tool

# 实例化路由器
login = APIRouter()

# Pydantic模型
class UserLoginRequest(BaseModel):
    username: str
    password: str

class UserRegisterRequest(BaseModel):
    username: str
    email: str
    password: str
    nickname: Optional[str] = None

class UserResponse(BaseModel):
    id: int
    username: str
    email: str
    nickname: Optional[str] = None
    user_type: str
    created_at: datetime
    status: str

class TokenResponse(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int
    user: UserResponse

# 装饰器：登录验证
def require_login(func):
    """装饰器：验证用户是否已登录"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        token = kwargs.get('token')
        if not token:
            raise HTTPException(status_code=401, detail="请先登录")

        try:
            payload = jwt_tool.verify_token(token)
            kwargs['user_id'] = payload.get('user_id')
            kwargs['username'] = payload.get('username')
            return func(*args, **kwargs)
        except Exception as e:
            raise HTTPException(status_code=401, detail=f"登录已过期: {str(e)}")
    return wrapper

# 装饰器：管理员权限
def require_admin(func):
    """装饰器：验证管理员权限"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        token = kwargs.get('token')
        if not token:
            raise HTTPException(status_code=401, detail="请先登录")

        try:
            payload = jwt_tool.verify_token(token)
            user_role = payload.get('role', 'user')

            if user_role != 'admin':
                raise HTTPException(status_code=403, detail="需要管理员权限")

            kwargs['user_id'] = payload.get('user_id')
            kwargs['username'] = payload.get('username')
            kwargs['role'] = user_role
            return func(*args, **kwargs)
        except Exception as e:
            raise HTTPException(status_code=401, detail=f"权限验证失败: {str(e)}")
    return wrapper

# 用户数据管理类
class UserManager:
    """用户管理类 - 演示静态方法和类方法"""

    # 模拟用户数据库（实际应该使用真实数据库）
    _users_db = {}

    @staticmethod
    def hash_password(password: str) -> str:
        """静态方法：密码哈希"""
        import hashlib
        return hashlib.sha256(password.encode()).hexdigest()

    @staticmethod
    def verify_password(password: str, hashed: str) -> bool:
        """静态方法：验证密码"""
        return UserManager.hash_password(password) == hashed

    @classmethod
    def create_user(cls, user_data: Dict[str, Any]) -> Dict[str, Any]:
        """类方法：创建用户"""
        user_id = len(cls._users_db) + 1
        user_data['id'] = user_id
        user_data['password_hash'] = cls.hash_password(user_data['password'])
        user_data['created_at'] = datetime.now()
        user_data['status'] = 'active'
        user_data['user_type'] = 'normal'

        # 深拷贝避免外部修改影响
        cls._users_db[user_id] = copy.deepcopy(user_data)
        return cls._users_db[user_id]

    @classmethod
    def get_user_by_username(cls, username: str) -> Optional[Dict[str, Any]]:
        """类方法：通过用户名获取用户"""
        for user in cls._users_db.values():
            if user['username'] == username:
                return copy.deepcopy(user)  # 返回深拷贝
        return None

    @staticmethod
    def get_user_by_id(user_id: int) -> Optional[Dict[str, Any]]:
        """静态方法：通过ID获取用户"""
        return UserManager._users_db.get(user_id)

    @staticmethod
    def update_user(user_id: int, update_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """静态方法：更新用户信息"""
        if user_id not in UserManager._users_db:
            return None

        # 深拷贝避免修改原始数据
        user = copy.deepcopy(UserManager._users_db[user_id])

        # 只更新允许的字段
        allowed_fields = {'nickname', 'email', 'bio'}
        for field in allowed_fields:
            if field in update_data:
                user[field] = update_data[field]

        UserManager._users_db[user_id] = user
        return user

# 登录相关API
@login.post("/register", response_model=UserResponse)
async def register(user_data: UserRegisterRequest):
    """用户注册 - 演示深浅拷贝和静态方法"""

    # 检查用户名是否已存在
    existing_user = UserManager.get_user_by_username(user_data.username)
    if existing_user:
        raise HTTPException(status_code=400, detail="用户名已存在")

    # 创建用户
    new_user_data = {
        "username": user_data.username,
        "email": user_data.email,
        "password": user_data.password,
        "nickname": user_data.nickname
    }

    user = UserManager.create_user(new_user_data)

    # 深拷贝用户信息，避免返回敏感数据
    safe_user = copy.deepcopy(user)
    if 'password_hash' in safe_user:
        del safe_user['password_hash']
    if 'password' in safe_user:
        del safe_user['password']

    return UserResponse(**safe_user)

@login.post("/login", response_model=TokenResponse)
async def user_login(user_data: UserLoginRequest):
    """用户登录 - 演示装饰器和JWT"""

    # 验证用户
    user = UserManager.get_user_by_username(user_data.username)
    if not user:
        raise HTTPException(status_code=400, detail="用户名或密码错误")

    if not UserManager.verify_password(user_data.password, user['password_hash']):
        raise HTTPException(status_code=400, detail="用户名或密码错误")

    # 创建JWT token
    user_payload = {
        "user_id": user["id"],
        "username": user["username"],
        "role": user["user_type"],
        "department": "default"
    }

    access_token = jwt_tool.create_access_token(user_payload)
    refresh_token = jwt_tool.create_refresh_token(user_payload)

    # 深拷贝用户数据，避免返回敏感信息
    safe_user = copy.deepcopy(user)
    del safe_user['password_hash']
    del safe_user['password']

    return TokenResponse(
        access_token=access_token,
        refresh_token=refresh_token,
        expires_in=3 * 3600,  # 3小时
        user=UserResponse(**safe_user)
    )

@login.post("/refresh-token")
async def refresh_token_endpoint(refresh_token: str):
    """刷新访问token"""
    try:
        new_access_token = jwt_tool.refresh_access_token(refresh_token)
        return {"access_token": new_access_token, "token_type": "bearer"}
    except Exception as e:
        raise HTTPException(status_code=401, detail=f"刷新token失败: {str(e)}")

@login.get("/profile")
@require_login
async def get_profile(user_id: int = None, token: str = None):
    """获取用户资料 - 演示装饰器认证"""
    if user_id is None:
        raise HTTPException(status_code=400, detail="请提供用户ID")

    user = UserManager.get_user_by_id(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")

    # 深拷贝并移除敏感信息
    safe_user = copy.deepcopy(user)
    del safe_user['password_hash']
    del safe_user['password']

    return UserResponse(**safe_user)

@login.put("/profile")
@require_login
async def update_profile(user_id: int, update_data: Dict[str, Any], token: str = None):
    """更新用户资料 - 演示深浅拷贝"""
    user = UserManager.update_user(user_id, update_data)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")

    # 深拷贝并移除敏感信息
    safe_user = copy.deepcopy(user)
    del safe_user['password_hash']
    del safe_user['password']

    return UserResponse(**safe_user)

@login.get("/users")
@require_admin
async def get_all_users(role: str = "admin", token: str = None):
    """获取所有用户 - 演示管理员权限装饰器"""
    users = []
    for user in UserManager._users_db.values():
        # 深拷贝并移除敏感信息
        safe_user = copy.deepcopy(user)
        del safe_user['password_hash']
        del safe_user['password']
        users.append(safe_user)

    return {"users": users, "total": len(users), "role": role}

# 导出路由器
__all__ = ["login"]